home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / uucico_s.lha / gio.c < prev    next >
C/C++ Source or Header  |  1992-12-06  |  21KB  |  1,008 lines

  1.  
  2. /*
  3.  *  GIO.C    WINDOWED G PROTOCOL
  4.  *
  5.  *  written from scratch, except the checksum routine which was
  6.  *  rewritten but based on the old one.
  7.  *
  8.  *  WINDOW SIZE:    When changing the window size be sure there
  9.  *            are enough buffers available for pending txs.
  10.  *
  11.  *  GIO.C (c)Copyright 1989, Matthew Dillon, All Rights Reserved
  12.  *  extended to window size of 7 by Jack J. Rouse
  13.  *
  14.  *  Added variable packetsize (SegSize, TxSegSize). <CB>
  15.  *
  16.  */
  17.  
  18. #include "includes.h"
  19.  
  20.  
  21. typedef unsigned char    ubyte;
  22. typedef unsigned short    uword;
  23.  
  24. typedef struct {
  25.     ubyte   Dle;    /*  Literal ASCII DLE                */
  26.     ubyte   K;        /*  data size 2^(K+4) except K=0 means no data  */
  27.     ubyte   CL,CH;    /*  MAGIC - chksum(data) ^ C        */
  28.     ubyte   C;
  29.     ubyte   X;        /*  K ^ C0 ^ C1 ^ C            */
  30. } Frame;
  31.  
  32. typedef struct {
  33.     ubyte   CType;    /*  bits 7-6 of C    */
  34.     ubyte   CCmd;    /*  bits 5-3 of C    */
  35.     ubyte   CSeq;    /*  bits 2-0 of C    */
  36.     ubyte   PLen;    /*  pre-data (2 bytes) for SHORTDATA type */
  37.     ubyte   *Data;    /*  implies CType=LONGDATA or SHORTDATA */
  38.     uword   DLen;    /*  length of data    */
  39. } Packet;
  40.  
  41. Prototype int gwrdata(FILE *);
  42. Prototype int gwrmsg(char *);
  43. Prototype int grddata(FILE *);
  44. Prototype int grdmsg(char *, int);
  45. Prototype int gturnon(int);
  46. Prototype int gturnoff(void);
  47. Prototype void ResetGIO(void);
  48.  
  49. Prototype short ReducedTimeout;
  50.  
  51. short ReducedTimeout;
  52.  
  53. Local      char *GetTxBuf(void);
  54. Local      int SendDataPacket(unsigned char *, int);
  55. Local      int RecvDataPacket(char **);
  56. Local      int GetData(int, Packet *);
  57. Local      int RecvdAck(char);
  58. Local      int WriteCtlPacket(int);
  59. Local      int WritePacket(Packet *, int);
  60. Local      int ReadPacket(Packet *, int);
  61. Local      int CheckSum(unsigned char *, int);
  62. Local      void FrameToPacket(Frame *, Packet *, unsigned char *);
  63. Local      int LenToK(unsigned short);
  64.  
  65. extern int debug;
  66. extern int WindowSize;
  67. extern int SegSize;
  68.  
  69. #define SUCCESS 0
  70. #define FAIL    1
  71.  
  72. #define MAGIC        0125252
  73. #define DLE        0x10
  74. #define WINDOWSIZE  7
  75. #define SEGSIZEK    2        /*  64 bytes ??        */
  76. #define SEGSIZEMAX  9        /*  4096 bytes max    <CB> */
  77.  
  78. #define SUB1(var)   (((var)-1)&7)
  79.  
  80.  
  81. #define CT_CONTROL    (0 << 6)
  82. #define CT_ALTCHN    (1 << 6)
  83. #define CT_LONGDATA    (2 << 6)
  84. #define CT_SHORTDATA    (3 << 6)
  85. #define CT_MASK     (3 << 6)
  86.  
  87. #define CC_CLOSE    (1 << 3)
  88. #define CC_RJ        (2 << 3)
  89. #define CC_SRJ        (3 << 3)
  90. #define CC_RR        (4 << 3)
  91. #define CC_INITC    (5 << 3)
  92. #define CC_INITB    (6 << 3)
  93. #define CC_INITA    (7 << 3)
  94. #define CC_MASK     (7 << 3)
  95.  
  96. #define SEQ_MASK    7
  97.  
  98. #define WAIT_ACK    1
  99. #define WAIT_DATA    2
  100. #define WAIT_CONTROL    3
  101.  
  102. #define MaxPktSize    4096
  103.  
  104. char    RxBuf[MaxPktSize+4];
  105. char    *TxBuf[8];
  106.  
  107.                 /*  TRANSMIT STAGE        */
  108. char    TxSeq = 0;        /*  Last send packet        */
  109. char    TxPend= 0;        /*  hasn't been acked yet   */
  110. uword    TxWinSize;        /*  1 or 2 (max 7)          */
  111. uword    TxSegSize;        /*  maximum segment size    */
  112. char    TxSegK;         /*  K for TxSegSize        */
  113. Packet    TxPacket[8];        /*  contents of last packet */
  114.  
  115.                 /*  RECEIVE STAGE        */
  116. char    RxSeq = 0;        /*  Last valid recv pkt     */
  117. char    RxRdy = 0;        /*  Has come in..        */
  118. char    RxRetry = 8;
  119. char    RxNotAcked = 0;     /*  We have yet to ack it   */
  120. Packet    RxPacket;        /*  The packet that has come in */
  121.  
  122. long Tot_Retries;
  123. long Tot_Packets;
  124.  
  125. void
  126. ResetGIO()
  127. {
  128.     TxSeq = 0;
  129.     TxPend= 0;
  130.     TxWinSize = 0;
  131.     TxSegSize = 0;
  132.     TxSegK = 0;
  133.     RxSeq = 0;
  134.     RxRdy = 0;
  135.     RxRetry = 8;
  136.     RxNotAcked = 0;
  137. }
  138.  
  139. /*
  140.  *  Get Transmit Buffer.  Note that some space to the left is available
  141.  */
  142.  
  143. Local
  144. char *
  145. GetTxBuf()
  146. {
  147.     static int index = 0;
  148.  
  149.     if (++index > TxWinSize)
  150.     index = 0;
  151.     if (TxBuf[index] == NULL
  152.     &&    (TxBuf[index] = (char *)malloc(MaxPktSize+4)) == NULL)
  153.     {
  154.     printf("Out of memory in GetTxBuf.");
  155.     /* could handle this case better, but it should be rare */
  156.     xexit(1);
  157.     }
  158.     return(TxBuf[index] + 2);
  159. }
  160.  
  161. int
  162. gwrdata(fi)
  163. FILE *fi;
  164. {
  165.     int bytes;
  166.  
  167.     if (debug > 7)
  168.     printf("GWRDATA: ");
  169.  
  170.     for (;;) {
  171.     char *buf = GetTxBuf();
  172.     if ((bytes = fread(buf, 1, TxSegSize, fi)) <= 0)
  173.         break;
  174.     BytesOut += bytes;
  175.     if (SendDataPacket(buf, bytes) != SUCCESS) {
  176.         if (debug > 7)
  177.         printf("GWR Failed\n");
  178.         return(FAIL);
  179.     }
  180.     if (debug > 7)
  181.         printf("\nGWROK ");
  182.     }
  183.     {
  184.     char *buf = GetTxBuf();
  185.     if (SendDataPacket(buf, 0) != SUCCESS) {
  186.         if (debug > 7)
  187.         printf("GWR Failed (last)\n");
  188.         return(FAIL);
  189.     }
  190.     }
  191.     if (debug > 7)
  192.     printf("\nGWFile Last Ack\n");
  193.     while (TxPend) {
  194.     if (GetData(WAIT_ACK, NULL) == FAIL)
  195.         return(FAIL);
  196.     }
  197.     if (debug > 7)
  198.     printf("success\n");
  199.     return (SUCCESS);
  200. }
  201.  
  202. /*
  203.  *  Write message to the other guy.
  204.  *
  205.  *  NOTE: LONGDATA packets used exclusively and \0 fill to end.
  206.  */
  207.  
  208. int
  209. gwrmsg(str)
  210. char *str;
  211. {
  212.     int len = strlen(str) + 1;      /*  type + str + \0  */
  213.  
  214.     if (debug > 7)
  215.     printf("GWRMSG: %s\n", str);
  216.  
  217.     while (len > TxSegSize) {
  218.     char *buf = GetTxBuf();
  219.     movmem(str, buf, TxSegSize);
  220.     if (debug > 7)
  221.         printf("GWR-SEND %d\n", TxSegSize);
  222.     if (SendDataPacket(buf, TxSegSize) != SUCCESS)
  223.         return(FAIL);
  224.     len -= TxSegSize;
  225.     str += TxSegSize;
  226.     }
  227.  
  228.     /*
  229.      *    Find optimal packet size (remember, we must force LONGDATA
  230.      *
  231.      *    Apparently packet sizes less than the agreed upon size are
  232.      *    not allowed ???
  233.      */
  234.  
  235.     {
  236.     short siz = TxSegSize;
  237.     char *buf = GetTxBuf();
  238. #ifdef NOTDEF
  239.     short k = TxSegK;
  240.  
  241.     while (k > 1 && (siz >> 1) >= len) {
  242.         --k;
  243.         siz >>= 1;
  244.     }
  245. #endif
  246.     if (debug > 7)
  247.         printf("GWR-FNL %d %d\n", len, siz);
  248.  
  249.     movmem(str, buf, len);
  250.     setmem(buf + len, siz - len, 0);
  251.     if (SendDataPacket(buf, siz) != SUCCESS) {
  252.         if (debug > 7)
  253.         printf("GWR-FAIL\n");
  254.         return(FAIL);
  255.     }
  256.     }
  257.     if (debug > 7)
  258.     printf("GWR Last Ack\n");
  259.     while (TxPend) {
  260.     if (GetData(WAIT_ACK, NULL) == FAIL)
  261.         return(FAIL);
  262.     }
  263.     if (debug > 7)
  264.     printf("success\n");
  265.     return (SUCCESS);
  266. }
  267.  
  268. int
  269. grddata(fi)
  270. FILE *fi;
  271. {
  272.     int bytes;
  273.     char *buf;
  274.  
  275.     if (debug > 7)
  276.     printf("GRDDATA\n");
  277.     while ((bytes = RecvDataPacket(&buf)) > 0) {
  278.     if (debug > 7)
  279.         printf("GRDDATA blk %d\n", bytes);
  280.     fwrite(buf, 1, bytes, fi);
  281.     BytesIn += bytes;
  282.     }
  283.     if (debug > 7)
  284.     printf("GRDDATA end %d\n", bytes);
  285.     if (bytes < 0)
  286.     return(FAIL);
  287.     else
  288.     return(SUCCESS);
  289. }
  290.  
  291. int
  292. grdmsg(buf, maxlen)
  293. char *buf;
  294. {
  295.     short i;
  296.     short n;
  297.     short slen;
  298.     char *ptr;
  299.  
  300.     i = 0;
  301.     if (debug > 7)
  302.     printf("GRDMSG\n");
  303.     while ((n = RecvDataPacket(&ptr)) > 0) {
  304.     ptr[n] = 0;
  305.     slen = strlen(ptr);
  306.     if (slen > maxlen - 1) {
  307.         printf("GRDMSG: Buffer overflow!\n");
  308.         return (FAIL);
  309.     }
  310.     movmem(ptr, buf + i, slen);
  311.     buf[i + slen] = 0;
  312.     if (slen != n)
  313.         break;
  314.     i += slen;
  315.     maxlen -= slen;
  316.     }
  317.     if (debug > 7)
  318.     printf("GRDMSGEND %d (%d) %s\n", n, i, buf);
  319.     if (n < 0) {
  320.     buf[0] = 0;
  321.     return(FAIL);
  322.     }
  323.     return(SUCCESS);
  324. }
  325.  
  326. Local
  327. int
  328. SendDataPacket(buf, bytes)
  329. ubyte *buf;
  330. int bytes;
  331. {
  332.     Packet  P;
  333.  
  334.     /*
  335.      *    If window exhausted we must wait for at least one ack.
  336.      */
  337.  
  338.     while (TxPend == TxWinSize) {
  339.     if (GetData(WAIT_ACK, NULL) == FAIL)
  340.         return(FAIL);
  341.     }
  342.  
  343.     TxSeq = (TxSeq + 1) & 7;        /*  next Tx packet  */
  344.  
  345.     /*
  346.      *    Figure out best fit packet size.  Apparently packets smaller
  347.      *    then the agreed upon size are not allowed ???
  348.      */
  349.  
  350. #ifdef NOTDEF
  351.     {
  352.     short k = TxSegK;
  353.     P.DLen = TxSegSize;
  354.     while (k > 1 && P.DLen && (P.DLen >> 1) >= bytes) {
  355.         --k;
  356.         P.DLen >>= 1;
  357.     }
  358.     }
  359. #else
  360.     P.DLen = TxSegSize;
  361. #endif
  362.  
  363.     if (bytes < P.DLen) {
  364.     uword extra = P.DLen - bytes;
  365.     setmem(buf + bytes, extra, 0);
  366.     if (extra <= 127) {
  367.         P.PLen = 1;
  368.         buf[-1] = extra;
  369.     } else {
  370.         P.PLen = 2;
  371.         buf[-2] = 0x80 | extra;
  372.         buf[-1] = (extra >> 7);
  373.     }
  374.     P.CType = CT_SHORTDATA;
  375.     } else {
  376.     P.PLen = 0;
  377.     P.CType = CT_LONGDATA;
  378.     }
  379.     P.CCmd = TxSeq << 3;    /*  transmit sequence number */
  380.     P.CSeq = RxSeq;        /*  last valid received pkt  */
  381.     P.Data = buf;
  382.  
  383.     if (debug > 7)
  384.     printf("WRITE DATA PACKET txseq=%d rxack=%d\n", TxSeq, P.CSeq);
  385.  
  386. #ifdef NOTDEF
  387.     RxNotAcked = 0;        /*  We've acked the rx packet */
  388. #else
  389.     if (RxNotAcked) {           /*  always send CC_RR packets */
  390.     WriteCtlPacket(CC_RR | RxSeq);
  391.     RxNotAcked = 0;
  392.     }
  393. #endif
  394.  
  395.     TxPacket[TxSeq] = P;
  396.     ++TxPend;
  397.  
  398.     WritePacket(&TxPacket[TxSeq], 1);
  399.     ++Tot_Packets;
  400.     
  401.     return(SUCCESS);
  402. }
  403.  
  404. Local
  405. int
  406. RecvDataPacket(pbuf)
  407. char **pbuf;
  408. {
  409.     if (RxRdy == 0) {
  410.     if (GetData(WAIT_DATA, NULL) != SUCCESS)
  411.         return(-1);
  412.     }
  413.     *pbuf = RxPacket.Data;
  414.     RxRdy = 0;
  415.     return((int)RxPacket.DLen);
  416. }
  417.  
  418. int
  419. gturnon(master)
  420. int master;
  421. {
  422.     Packet P;
  423.     short retry = 5;
  424.     short windowsize = WINDOWSIZE;    /*  our prefered window size    */
  425.     short segsize = SEGSIZEK;        /*  our prefered segment size    */
  426.  
  427.     if (WindowSize < windowsize)        /*  command line override       */
  428.     windowsize = WindowSize;
  429.  
  430.     if (SegSize > segsize && SegSize < SEGSIZEMAX)
  431.     segsize = SegSize;        /*  added by <CB> */
  432.     if (debug > 0)
  433.     printf("Proposed SegSize is %d\n", segsize);
  434.  
  435.     if (master) {
  436.     while (retry > 0) {
  437.         WriteCtlPacket(CC_INITA | windowsize);
  438.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
  439.         if (P.CSeq && P.CSeq < windowsize)
  440.             windowsize = P.CSeq;
  441.         break;
  442.         }
  443.         --retry;
  444.     }
  445.     while (retry > 0) {
  446.         WriteCtlPacket(CC_INITB | (segsize - 1));
  447.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
  448.         if (P.CSeq < segsize - 1)
  449.             segsize = P.CSeq + 1;
  450.         break;
  451.         }
  452.         --retry;
  453.     }
  454.     while (retry > 0) {
  455.         WriteCtlPacket(CC_INITC | windowsize);
  456.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
  457.         if (P.CSeq && P.CSeq < windowsize)
  458.             windowsize = P.CSeq;
  459.         break;
  460.         }
  461.         --retry;
  462.     }
  463.     } else {
  464.     while (retry > 0) {
  465.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
  466.         WriteCtlPacket(CC_INITA | windowsize);
  467.         if (P.CSeq && windowsize > P.CSeq)
  468.             windowsize = P.CSeq;
  469.         break;
  470.         }
  471.         --retry;
  472.     }
  473.     while (retry > 0) {
  474.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
  475.         WriteCtlPacket(CC_INITB | (segsize - 1));
  476.         if (P.CSeq < segsize - 1)
  477.             segsize = P.CSeq + 1;
  478.         break;
  479.         }
  480.         --retry;
  481.     }
  482.     while (retry > 0) {
  483.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
  484.         WriteCtlPacket(CC_INITC | windowsize);
  485.         if (P.CSeq && windowsize > P.CSeq)
  486.             windowsize = P.CSeq;
  487.         break;
  488.         }
  489.         --retry;
  490.     }
  491.     }
  492.     TxSegK = segsize;
  493.     TxSegSize = 1 << (TxSegK + 4);
  494.     TxWinSize = windowsize;
  495.  
  496.     xfer.proto[0] = 'g';
  497.     xfer.proto[1] = TxWinSize;
  498.     xfer.proto[2] = TxSegK;
  499.  
  500.     if (debug > 0) {
  501.     printf("Window Size is %d\n", TxWinSize);
  502.     printf("Segment Size is %d (%d bytes)\n", TxSegK, TxSegSize);
  503.     }
  504.     if (retry == 0)
  505.     return(FAIL);
  506.     return(SUCCESS);
  507. }
  508.  
  509. int
  510. gturnoff()
  511. {
  512.     Packet P;
  513.     short retry = 5;
  514.  
  515.     if (RxNotAcked) { /* ack last data packet sent (presumably master's HY) */
  516.     WriteCtlPacket(CC_RR | RxSeq);
  517.     RxNotAcked = 0;
  518.     }
  519.  
  520.     while (retry > 0) {
  521.     WriteCtlPacket(CC_CLOSE);
  522.     if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_CLOSE)
  523.         return (SUCCESS);
  524.     --retry;
  525.     }
  526.     return (FAIL);
  527. }
  528.  
  529. /*
  530.  *  GetData()
  531.  *
  532.  *  This is the core of the packet protocol.  As soon as we get a satisfactory
  533.  *  terminating condition we return.  However, on unsatisfactory conditions
  534.  *  such as having to send a reject, we attempt to drain any pending data
  535.  *  (i.e. multiple returned rejects) so we do not do multiple resends.
  536.  *
  537.  *  The resend flag only applies on a failure return.
  538.  */
  539.  
  540. Local
  541. int
  542. GetData(waitfor, p)
  543. int waitfor;
  544. Packet *p;
  545. {
  546.     Packet P;
  547.     short timeout;
  548.     short drainmode = 0;
  549.  
  550.     /*
  551.      *    If we haven't acked the last packet we received we must do
  552.      *    so now before we can expect to receive another one!
  553.      */
  554.  
  555.     if (debug > 7)
  556.     printf("Get-Data waitfor %s\n", (waitfor == WAIT_ACK) ? "WAIT_ACK" : "WAIT_DATA");
  557.     if (waitfor == WAIT_ACK)
  558.     timeout = (PacketTimeout) ? PacketTimeout : 5;
  559.     else if (waitfor == WAIT_DATA)
  560.     timeout = (PacketTimeout) ? PacketTimeout * 4 : 20;
  561.     else
  562.     timeout = (PacketTimeout) ? PacketTimeout * 4 : 20;
  563.  
  564.     for (;;) {
  565.     /*
  566.      *  due to confusion on connection termination, we do not wait
  567.      *  around trying to retry the final termination acknowlege.
  568.      */
  569.  
  570.     if (ReducedTimeout) {
  571.         if (RxRetry > 2)
  572.         RxRetry = 2;
  573.         if (timeout > 5)
  574.         timeout = 5;
  575.     }
  576.     if (RxNotAcked) {                   /*  good, send ack for rx'd pkt */
  577.         WriteCtlPacket(CC_RR | RxSeq);
  578.         RxNotAcked = 0;
  579.     }                    /*    bad, timeout on read        */
  580.     if (ReadPacket(&P, (drainmode) ? 0 : timeout) == FAIL) {
  581.         drainmode = 0;
  582.  
  583. /*
  584.  * fail if greater than %20 packets overall retries.
  585.  */
  586. #define ERROR_THRESHOLD (Tot_Packets < 50 || (Tot_Packets/(Tot_Retries+1)) > 4)
  587.  
  588.         /*
  589.          *    If we have timed out waiting for data then send a reject
  590.          */
  591.  
  592.         if (waitfor == WAIT_DATA) {
  593.  
  594.         if (RxRetry && ERROR_THRESHOLD) { 
  595.             --RxRetry;
  596.                     /*
  597.                      * sd: To properly drain on errors I found a small 
  598.                      *     delay was needed here.
  599.                      */
  600.                     Delay(15L);
  601.                     ++Tot_Retries;
  602.                     
  603.             if (debug > 7)
  604.             printf("\nWAIT-DATA, TIMEOUT, SEND RJ\n");
  605.             WriteCtlPacket(CC_RJ | RxSeq);
  606.             continue;
  607.         }
  608.         }
  609.  
  610.         /*
  611.          *    If we have timed out waiting for an ack send the entire
  612.          *    window.  We must send the window sometime and it might as
  613.          *    well be now.
  614.          */
  615.  
  616.         if (waitfor == WAIT_ACK) {
  617.         if (RxRetry && ERROR_THRESHOLD) { 
  618.             int i;
  619.  
  620.             if (debug > 7)
  621.             printf("RESEND %d packets\n", TxPend);
  622.             for (i = 1; i <= TxPend; ++i) {
  623.             Packet *p = &TxPacket[(TxSeq - TxPend + i) & 7];
  624.             p->CSeq = RxSeq;
  625.             WritePacket(p, 1);
  626.             }
  627.             --RxRetry;
  628.                     ++Tot_Retries;
  629.             continue;
  630.         }
  631.         }
  632.         if (debug > 7)
  633.         printf("COMPLETE FAILURE RxRetry = %d\n", RxRetry);
  634.         return(FAIL);
  635.     }
  636.  
  637.     /*
  638.      *  valid packet, terminating condition?
  639.      */
  640.  
  641.     RxRetry = 8;
  642.     switch(P.CType) {
  643.     case CT_CONTROL:
  644.         switch(P.CCmd) {
  645.         case CC_CLOSE:  /*    End of communication ... not an ACK!       */
  646.         if (waitfor == WAIT_CONTROL) {
  647.             *p = P;
  648.             return(SUCCESS);
  649.         }
  650.         return(FAIL);
  651.         case CC_RJ:     /*    Reject packet (P.CSeq == last good packet) */
  652.         (void)RecvdAck(P.CSeq);
  653.         drainmode = 1;
  654.         break;
  655.         case CC_SRJ:    /*    Selective Reject (P.CSeq == bad packet # ) */
  656.         return(FAIL);
  657.         case CC_RR:     /*    Ack to packet  (P.CSeq == packet # acked)   */
  658. #ifdef NOTDEF
  659.         if (P.CSeq == ((TxSeq - TxPend) & 7)) {
  660.             /*
  661.              * The CSeq packet was previously acknowledged
  662.              * The receiver apparently has not seen anything since.
  663.              * This is the same as a rejection.
  664.              */
  665.             goto resend;
  666.         }
  667. #endif
  668.         if (RecvdAck(P.CSeq) == SUCCESS && waitfor == WAIT_ACK)
  669.             return(SUCCESS);
  670.         else
  671.             drainmode = 1;    /* .19    */
  672.         break;
  673.         case CC_INITC:
  674.         case CC_INITB:
  675.         case CC_INITA:
  676.         if (waitfor == WAIT_CONTROL) {
  677.             *p = P;
  678.             return(SUCCESS);
  679.         }
  680.         return(FAIL);
  681.         }
  682.         break;
  683.     case CT_ALTCHN:
  684.         printf("ALTCHN packet ??\n");
  685.         break;
  686.     case CT_LONGDATA:
  687.     case CT_SHORTDATA:
  688.         {
  689.         char rxseq = P.CCmd >> 3;
  690.         char txack = P.CSeq;
  691.  
  692.         if (RxRdy == 1) {
  693.             printf("Got two receive packets without me acking!\n");
  694.         }
  695.  
  696.         if (rxseq == RxSeq) {   /*  already got this packet */
  697.             RxNotAcked = 1;
  698.             continue;
  699.                     /*  expected packet?        */
  700.         } else if (rxseq != ((RxSeq + 1) & 7)) {
  701.             drainmode = 1;
  702.             printf("Received sequence %d, expected %d\n", rxseq, (RxSeq + 1) & 7);
  703.             break;
  704.         }
  705.         if (debug > 6)
  706.             printf("RECV SEQUENCE %d\n", rxseq);
  707.  
  708.         RecvdAck(txack);    /*  woa */
  709.  
  710.         /*
  711.          *  Delay sending the ACK back in case we can combine
  712.          *  it with the next transmitted packet.
  713.          */
  714.  
  715.         RxNotAcked = 1;     /*  we haven't ack'd the rx packet */
  716.  
  717.                 ++Tot_Packets;
  718.  
  719.         RxSeq = (RxSeq + 1) & 7;
  720.         RxRdy = 1;
  721.         RxPacket = P;
  722.         if (waitfor == WAIT_DATA)
  723.             return(SUCCESS);
  724.         if (TxPend == 0 && waitfor == WAIT_ACK)
  725.             return(SUCCESS);
  726.         }
  727.         break;
  728.     }
  729.     }
  730. }
  731.  
  732. Local
  733. int
  734. RecvdAck(seq)
  735. char seq;
  736. {
  737.     short i;
  738.  
  739.     /*
  740.      *    which packet was acked?
  741.      */
  742.  
  743.     for (i = 0; i < TxPend; ++i) {
  744.     if (seq == ((TxSeq - i) & 7))
  745.         break;
  746.     }
  747.     if (i && i == TxPend) {
  748.     if (seq != ((TxSeq - TxPend) & 7))
  749.         printf("He acked the wrong packet! %d expected %d\n", seq, TxSeq);
  750.     return(FAIL);
  751.     }
  752.     if (debug > 7)
  753.     printf("TxPend %d -> %d\n", TxPend, i);
  754.     TxPend = i;
  755.     return(SUCCESS);
  756. }
  757.  
  758. Local
  759. int
  760. WriteCtlPacket(cc)
  761. int cc;
  762. {
  763.     Packet pk;
  764.  
  765.     pk.CType = CT_CONTROL;
  766.     pk.CCmd  = cc & CC_MASK;
  767.     pk.CSeq  = cc & SEQ_MASK;
  768.     pk.PLen  = 0;
  769.     pk.DLen  = 0;
  770.     WritePacket(&pk, 0);
  771.     return(SUCCESS);
  772. }
  773.  
  774. Local
  775. int
  776. WritePacket(pk, async)
  777. Packet *pk;
  778. int async;
  779. {
  780.     Frame   F;
  781.     uword   sum;
  782.  
  783.     F.Dle = DLE;
  784.     F.C   = pk->CType | pk->CCmd | pk->CSeq;
  785.     F.K   = 9;
  786.  
  787.     if (pk->CType == CT_SHORTDATA || pk->CType == CT_LONGDATA)
  788.     F.K = LenToK(pk->DLen);
  789.     else
  790.     pk->DLen = 0;
  791.  
  792.     sum = MAGIC - (CheckSum(pk->Data - pk->PLen, pk->DLen) ^ F.C);
  793.  
  794.     F.CH  = sum >> 8;
  795.     F.CL  = sum;
  796.     F.X   = F.K ^ F.CH ^ F.CL ^ F.C;
  797.  
  798.     if (debug > 7)
  799.     printf("WritePacket: F.K = %d F.C = %d.%d.%d\n", F.K, F.C >> 6, (F.C >> 3) & 7, F.C & 7);
  800.  
  801.     if (async)
  802.     xwritea(&F, sizeof(F));
  803.     else
  804.     xwrite(&F, sizeof(F));      /*  write header    */
  805.     if (pk->DLen) {             /*  write data      */
  806.     if (async)
  807.         xwritea(pk->Data - pk->PLen, pk->DLen);
  808.     else
  809.         xwrite(pk->Data - pk->PLen, pk->DLen);
  810.     }
  811.     return(SUCCESS);
  812. }
  813.  
  814. Local
  815. int
  816. ReadPacket(pk, timeout)
  817. Packet *pk;
  818. int timeout;
  819. {
  820.     Frame   F;
  821.     short   c;
  822.     short   i = 0;
  823.  
  824.     pk->Data = RxBuf;
  825.     pk->CType = 0xFF;
  826.     pk->CCmd  = 0;
  827.     pk->CSeq  = 0;
  828.  
  829.     if (debug > 7)
  830.     printf("ReadPacket\n");
  831.     while ((c = xgetc(timeout)) != EOF) {
  832.     if (debug > 8)
  833.         printf("RP %d %02x\n", i, c);
  834.  
  835.     switch(i) {
  836.     case 0:
  837.         if (c == DLE) {
  838.         F.Dle = c;
  839.         ++i;
  840.         if (timeout == 0)
  841.             timeout = 1;
  842.         }
  843.         break;
  844.     case 1:
  845.         F.K = c;
  846.         ++i;
  847.         if (c == DLE) { /*  K only valid 1-9    */
  848.         F.Dle = c;
  849.         i = 1;
  850.         }
  851.         else if (c == 0 || c > 9)
  852.         i = 0;
  853.         break;
  854.     case 2:
  855.         F.CL = c;
  856.         ++i;
  857.         break;
  858.     case 3:
  859.         F.CH = c;
  860.         ++i;
  861.         break;
  862.     case 4:
  863.         F.C = c;
  864.         ++i;
  865.         break;
  866.     case 5:
  867.         F.X = c;
  868.         if (F.X != (F.K ^ F.CH ^ F.CL ^ F.C)) {
  869.         printf("F.X failed: %02x %02x\n", F.X, (F.K ^ F.CH ^ F.CL ^ F.C));
  870.         i = 0;
  871.         } else {        /*    get data segment if any */
  872.         ++i;
  873.         }
  874.         break;
  875.     }
  876.     if (i == 6)
  877.         break;
  878.     }
  879.     if (debug > 7) {
  880.     if (i)
  881.         printf("RP Hdr i = %d, F.K = %d F.C = %d.%d.%d\n", i, F.K, F.C >> 6, (F.C >> 3) & 7, F.C & 7);
  882.     else
  883.         printf("RP Hdr <rx timeout>\n");
  884.     }
  885.  
  886.     if (i == 6) {       /*  Receive Data Portion    */
  887.     uword pktsize = 1 << (F.K + 4);
  888.     uword n;
  889.  
  890.     if (F.K == 9)
  891.         pktsize = 0;
  892.  
  893.     if (pktsize > MaxPktSize) {
  894.         printf("Protocol failure pktsize %d/%d/%d\n", pktsize, TxSegSize, MaxPktSize);
  895.         return (FAIL);
  896.     }
  897.     for (n = 0; n < pktsize; ++n) {
  898.         if ((c = xgetc(4)) == EOF)
  899.         break;
  900.         pk->Data[n] = c;
  901.     }
  902.     if (c != EOF) {
  903.         uword hissum;
  904.         uword oursum;
  905.         hissum = (F.CH << 8) | F.CL;
  906.         oursum = MAGIC - (CheckSum(pk->Data, pktsize) ^ F.C);
  907.         if (debug > 7)
  908.         printf("Got Data, checking: %04x %04x\n", hissum, oursum);
  909.         if (hissum == oursum) {
  910.         FrameToPacket(&F, pk, pk->Data);
  911.         return (SUCCESS);
  912.         }
  913.     } else {
  914.         FrameToPacket(&F, pk, pk->Data);    /* mainly for pk->CType */
  915.         return (FAIL);
  916.     }
  917.     }
  918.     /*
  919.      *    Timeout, retry?
  920.      */
  921.     return (FAIL);
  922. }
  923.  
  924. Local
  925. int
  926. CheckSum(s, n)
  927. ubyte *s;
  928. int n;
  929. {
  930.     uword sum;
  931.     uword x;
  932.     uword t;
  933.  
  934.     if (n == 0)
  935.     return(0);
  936.     sum = -1;
  937.     x = 0;
  938.  
  939.     while (n) {
  940.     if (sum & 0x8000)
  941.         sum = (sum << 1) | 1;
  942.     else
  943.         sum = (sum << 1);
  944.  
  945.     t = sum;
  946.     sum += *s++;
  947.     x += sum ^ n;
  948.     if (sum <= t)
  949.         sum ^= x;
  950.     --n;
  951.     }
  952.     return((int)sum);
  953. }
  954.  
  955. Local
  956. void
  957. FrameToPacket(fr, pk, data)
  958. Frame *fr;
  959. Packet *pk;
  960. ubyte *data;
  961. {
  962.     pk->CType = fr->C & CT_MASK;
  963.     pk->CCmd  = fr->C & CC_MASK;
  964.     pk->CSeq  = fr->C & SEQ_MASK;
  965.     switch(pk->CType) {
  966.     case CT_LONGDATA:
  967.     pk->DLen = 1 << (fr->K + 4);
  968.     break;
  969.     case CT_SHORTDATA:
  970.     pk->DLen = 1 << (fr->K + 4);
  971.     if (pk->Data[0] & 0x80) {
  972.         pk->DLen -= (pk->Data[0] & 0x7F) | (pk->Data[1] << 7);
  973.         if (pk->DLen < 0) {
  974.         printf("DLEN ERROR %d\n", pk->DLen);
  975.         pk->DLen = 0;
  976.         }
  977.         pk->Data += 2;
  978.     } else {
  979.         pk->DLen -= *pk->Data;
  980.         ++pk->Data;
  981.     }
  982.     break;
  983.     default:
  984.     pk->DLen = 0;
  985.     break;
  986.     }
  987. }
  988.  
  989. Local
  990. int
  991. LenToK(bytes)
  992. uword bytes;
  993. {
  994.     uword n = 32;
  995.     uword k = 1;
  996.  
  997.     while (n < bytes) {
  998.     n <<= 1;
  999.     ++k;
  1000.     }
  1001.     if (k > 8) {
  1002.     printf("Soft error, LenToK: %d %d %d\n", bytes, n, k);
  1003.     k = 8;
  1004.     }
  1005.     return((int)k);
  1006. }
  1007.  
  1008.